package drds.server.sqlparser.parser;

import drds.server.sqlparser.sqlobject.expression.Expression;
import drds.server.sqlparser.sqlobject.expression.name.IName;
import drds.server.sqlparser.sqlobject.expression.name.Identifier;
import drds.server.sqlparser.sqlobject.statement.Statement;
import drds.server.sqlparser.sqlobject.statement.delete.DeleteStatement;
import drds.server.sqlparser.sqlobject.statement.insert.InsertStatement;
import drds.server.sqlparser.sqlobject.statement.insert.ValueList;
import drds.server.sqlparser.sqlobject.statement.query.SelectStatement;
import drds.server.sqlparser.sqlobject.statement.query.SubQuery;
import drds.server.sqlparser.sqlobject.statement.update.UpdateSetItem;
import drds.server.sqlparser.sqlobject.statement.update.UpdateStatement;

/**
 * 
 * @author 曹正辉<330937205@qq.com>
 * 
 */
public class StatementParser extends SqlParser {

	protected ExpressionParser expressionParser;

	public StatementParser(String sql) {
		this(new ExpressionParser(sql));
	}

	public StatementParser(ExpressionParser expressionParser) {
		super(expressionParser.getLexer());
		this.expressionParser = expressionParser;
	}

	public ExpressionParser getExpressionParser() {
		return expressionParser;
	}

	public Statement parseStatement() {

		if (lexer.getMark() == Mark.SELECT) {
			return parseSelect();
		}
		if (lexer.getMark() == (Mark.INSERT)) {
			return parseInsertStatement();
		}
		if (lexer.getMark() == (Mark.UPDATE)) {
			return parseUpdateStatement();
		}
		if (lexer.getMark() == (Mark.DELETE)) {
			return parseDeleteStatement();
		}

		printError(lexer.getMark());
		return null;

	}

	public Statement parseInsertStatement() {

		InsertStatement insertStatement = new InsertStatement();

		accept(Mark.INSERT);
		lexer.nextMark();
		accept(Mark.INTO);
		lexer.nextMark();
		IName tableName = this.expressionParser.parseName();
		insertStatement.setTableName(tableName);
		accept(Mark.LEFT_PAREN);
		this.expressionParser.parseListExpression(insertStatement.getColumnNameList(), insertStatement);
		accept(Mark.RIGHT_PAREN);
		insertStatement.createColumnNameset();
		lexer.nextMark();
		accept(Mark.VALUES);
		lexer.nextMark();
		accept(Mark.LEFT_PAREN);
		ValueList valueList = new ValueList();
		this.expressionParser.parseListExpression(valueList.getValueList(), valueList);
		accept(Mark.RIGHT_PAREN);
		/**
		 * 需要对比参数和列名的个数是否一致。
		 */
		if (insertStatement.getColumnNameList().size() != valueList.getValueList().size()) {
			throw new RuntimeException("参数和列名的个数不一致");
		}
		insertStatement.setValueList(valueList);
		valueList.setColumnNameMap(insertStatement.getColumnNameList());
		return insertStatement;
	}

	public UpdateStatement parseUpdateStatement() {
		UpdateStatement udpateStatement = new UpdateStatement();
		accept(Mark.UPDATE);
		lexer.nextMark();
		IName tableName = this.expressionParser.parseName();
		udpateStatement.setTableName(tableName);
		//
		parseUpdateSetItem(udpateStatement);
		/**
		 * 不支持 (where) 1=1
		 */
		if (lexer.mark == Mark.WHERE) {
			accept(Mark.WHERE);
			lexer.nextMark();
			udpateStatement.setWhere(this.expressionParser.parseExpression());
		}
		return udpateStatement;
	}

	/**
	 * 结束的时候已经lexer.nextMark();
	 */
	protected void parseUpdateSetItem(UpdateStatement udpateStatement) {
		accept(Mark.SET);
		for (;;) {
			UpdateSetItem updateSetItem = parseUpdateSetItem();
			udpateStatement.addUpdateSetItem(updateSetItem);
			lexer.nextMark();
			if (lexer.getMark() != Mark.COMMA) {
				break;
			}

		}
	}

	public UpdateSetItem parseUpdateSetItem() {
		// accept(Mark.SET);
		lexer.nextMark();
		UpdateSetItem updateSetItem = new UpdateSetItem();
		updateSetItem.setColumnName(this.parseColmunName());
		System.out.println("当前name:" + updateSetItem.getColumnName());
		lexer.nextMark();
		accept(Mark.Equal);
		// 要么是值,要么是a=a+b a=b+c
		lexer.nextMark();
		updateSetItem.setValue(this.expressionParser.valueForUpdate());

		return updateSetItem;
	}

	/**
	 * 列名
	 */
	public Expression parseColmunName() {
		lexer.check(Mark.IDENTIFIER);
		return new Identifier(lexer.stringValue());
	}

	public DeleteStatement parseDeleteStatement() {
		DeleteStatement deleteStatement = new DeleteStatement();
		accept(Mark.DELETE);
		lexer.nextMark();
		accept(Mark.FROM);
		IName tableName = expressionParser.parseName();
		deleteStatement.setTableName(tableName);
		/**
		 * 至少where 1=1
		 */
		accept(Mark.WHERE);
		lexer.nextMark();
		Expression where = this.expressionParser.parseExpression();
		deleteStatement.setWhere(where);

		return deleteStatement;
	}

	/**
	 * 在分布式数据库服务里面不支持tableName.*原因是在服务端不能唯一确认*代表的字段是多少。
	 */
	public SelectStatement parseSelect() {

		SelectParser selectParser = new SelectParser(getLexer());
		SubQuery subQuery = selectParser.parseSubQuery();
		return new SelectStatement(subQuery);
	}

}
